package com.jie.component.validation.core;

import com.jie.component.exception.base.FrameException;
import com.jie.component.exception.base.ValidationException;
import com.jie.component.exception.enums.FrameError;
import com.jie.component.validation.annotion.Valid;
import com.jie.component.validation.factory.ValidatorFactory;
import com.jie.component.validation.validator.ConstraintValidator;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * @author jie
 * @version 1.0 2025-02-11 参数校验的执行器
 */
@Slf4j
@RequiredArgsConstructor
public class ValidationExecutor {

    private final ValidatorFactory validatorFactory;

    public void validate(Object object) {

        List<String> errors = new ArrayList<>();

        // 校验字段
        for (Field field : object.getClass().getDeclaredFields()) {
            field.setAccessible(true);
            validateField(field, object, errors);
        }

        if (!errors.isEmpty()) {
            throw new ValidationException(errors);
        }
    }

    private void validateField(Field field, Object object, List<String> errors) {
        try {
            Object value = field.get(object);
            // 获取字段上的所有注解
            for (Annotation annotation : field.getAnnotations()) {
                ConstraintValidator validator = validatorFactory.getValidator(annotation.annotationType());
                if (validator != null) {
                    log.info("执行参数校验：{} 校验器 {}", field.getName(), validator.getClass().getName());
                    if (!validator.isValid(value, annotation)) {
                        errors.add(String.format("字段 [%s] %s",
                                field.getName(),
                                validator.getMessage(annotation)));
                    }
                }
            }
            // 如果字段标记了@Valid，递归校验
            if (field.isAnnotationPresent(Valid.class) && value != null) {
                validate(value);
            }
        } catch (IllegalAccessException e) {
            throw new FrameException(FrameError.PARAM_VALIDATION);
        }
    }
}
